package main.kotlin.gui


import java.io.File
import java.io.IOException
import java.io.OutputStream
import java.io.PrintStream

import java.lang.Thread


import javafx.application.Application
import javafx.application.Platform
import javafx.embed.swing.SwingFXUtils
import javafx.scene.control.cell.*
import javafx.scene.control.*
import javafx.scene.layout.*
import javafx.event.EventHandler
import javafx.concurrent.Task
import javafx.beans.property.SimpleBooleanProperty
import javafx.beans.property.SimpleStringProperty
import javafx.beans.property.SimpleDoubleProperty

import javax.imageio.ImageIO

import kotlin.text.Regex

import tornadofx.*


import main.kotlin.singlePage.SinglePage



class MyApp: App(CLDownloader::class)

class CLDownloader: View() {
    override val root: VBox by fxml("../../resources/CLDownloader.fxml")
    var links = ArrayList<String>()  // 收集链接的列表
    val linkList : ListView<String> by fxid("linkList")  // list view

    private val output: TextField by fxid()         // 输出文件夹
    private val outputButton: Button by fxid("setOutput")
    private val linkInput: TextField by fxid("link")
    private val proxyIp : TextField by fxid("ip")
    private val proxyPort : TextField by fxid("port")
    private val messageText : TextArea by fxid("message")
    private val progress: ProgressBar by fxid("progress")
    private val downloadButton: Button by fxid("Download")

    private val helpMenu: MenuItem by fxid("help")
    private val aboutMenu: MenuItem by fxid("about")

    private val console = Console(messageText)
    private val ps = PrintStream(console, true)

//    private val taskStatus = TaskStatus()
    private val taskRuning = SimpleBooleanProperty()
    private val taskMessage = SimpleStringProperty()
    private val taskProgress = SimpleDoubleProperty()

    private val downloadTask = object: Task<Unit>() {
        override fun call() {
            updateMessage("Start to download")
            var ip: String? = null
            var port: String? = null

            if (proxyIpValidator.isValid) ip = proxyIp.text
            if (proxyPortValidator.isValid) port = proxyPort.text

            var outdir = System.getProperty("user.dir").toString()
            if (outputVilidator.isValid) {
                outdir = output.text
            }
            if (!(ip in listOf("", null) || (port in listOf("", null)))) {
                messageText.appendText("#".repeat(50) + "\n")
                messageText.appendText("使用代理: $ip:$port \n")
                messageText.appendText("#".repeat(50) + "\n")
            }

            for ((index, link) in links.withIndex()) {
                SinglePage(link, "GBK", messageText).saveTo(outdir, style = "pixyll")
                updateProgress((index + 1).toLong(), links.size.toLong())
            }
        }

        override fun succeeded() {
            updateMessage("下载完成")
            messageText.appendText("下载完成\n")
        }
    }

    private val downloadThread = Thread(this.downloadTask)


    /*
    添加各种验证功能

    */
    private val context = ValidationContext()

    private val linkInputValidator = context.addValidator(linkInput, linkInput.textProperty()) {
        val pattern = "^((https|http|ftp|rtsp|mms)?://)[^\\s]+".toRegex()

        if (it in listOf(null, "") || !pattern.matches(it.toString())) {
            error("请输入合法网址")
        } else {
            null
        }
    }

    private val proxyIpValidator = context.addValidator(proxyIp, proxyIp.textProperty()) {
        val ip = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\." +
                "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\." +
                "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\." +
                "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)"

        val pattern = Regex(ip)

        when (it) {
            null -> error("IP error")
            else -> {
                if (it.length > 3 && !pattern.matches(it)) error("IP error") else null
            }
        }

    }

    val proxyPortValidator = context.addValidator(proxyPort, proxyPort.textProperty()) {
        try {
            val text = it ?: ""

            if (text != "" && text.toInt() in 0..65536) null else error("Port error")
        } catch (e: NumberFormatException) {
            error("Port error")
        }
    }

    val outputVilidator = context.addValidator(output, output.textProperty()) {
        when (it) {
            null -> {
                output.text = System.getProperty("user.dir")
                error("输出路径错误，设定为工作路径")
            }
            else -> {
                if (File(it).isDirectory) {
                    null
                } else {
                    error("输出路径错误")
                }
            }
        }

    }

    init {
        /*
        通过javaClass.getResource和转换，成功从jar文件中读取导入icon
        */
        val iconUTL = javaClass.getResource("favicon.jpg")
        val iconBuffered = ImageIO.read(iconUTL)
        addStageIcon(SwingFXUtils.toFXImage(iconBuffered, null))

        linkList.items = links.observable()

        output.text = System.getProperty("user.dir").toString()
        chooseDirectory()
        /*
        * 初始化listView，contextmenu设定了右键菜单
        * cellFactory设定了可编辑功能
        * onEditCommit设定了如何接受编辑后的数据
        */
        setContextMenu()
        setListViewEditable()

        messageText.isEditable = false

        System.setOut(ps)
        System.setErr(ps)

        messageText.appendText("启动成功\n")

        helpMenu.onAction = EventHandler {
            openInternalWindow(Help::class)
        }
        aboutMenu.onAction = EventHandler {
            openInternalWindow(About::class)
        }

//        progress.progress = taskStatus.progress.doubleValue()

        taskRuning.bind(downloadTask.runningProperty())
        taskProgress.bind(downloadTask.progressProperty())
        taskMessage.bind(downloadTask.messageProperty())

    }

    private fun chooseDirectory() {
        outputButton.action {  // 指定输出目录
            val dir = chooseDirectory("选择输出目录")

            when (dir) {
                null -> output.text = System.getProperty("user.dir")
                else -> output.text = dir.toString()
            }
        }
    }

    private fun setContextMenu() {
        linkList.contextmenu {
            item("删除").setOnAction {
                links.remove(linkList.selectedItem)
                linkList.items = links.observable()
            }
        }
    }

    private fun setListViewEditable() {
        linkList.isEditable = true

        linkList.cellFactory = TextFieldListCell.forListView()

        linkList.onEditCommit = EventHandler<ListView.EditEvent<String>> {
            val index = links.indexOf(linkList.selectedItem)
            links.remove(linkList.selectedItem)
            links.add(index, it.newValue)
            linkList.items = links.observable()
        }
    }

    fun addLink() { // 添加链接按钮的功能
        if (linkInputValidator.isValid && linkInput.text !in listOf(null, "")) {
            messageText.appendText("添加链接 ${linkInput.text}\n")
            links.add(linkInput.text)
            linkList.items = links.observable()
            linkInput.text = ""
        }
    }

    fun download() {
        this.downloadThread.start()
        // runAsync(true, taskStatus) {

        //     var ip: String? = null
        //     var port: String? = null

        //     if (proxyIpValidator.isValid) ip = proxyIp.text
        //     if (proxyPortValidator.isValid) port = proxyPort.text

        //     var outdir = System.getProperty("user.dir").toString()
        //     if (outputVilidator.isValid) {
        //         outdir = output.text
        //     }
        //     if (!(ip in listOf("", null) || (port in listOf("", null)))) {
        //         messageText.appendText("#".repeat(50) + "\n")
        //         messageText.appendText("使用代理: $ip:$port \n")
        //         messageText.appendText("#".repeat(50) + "\n")
        //     }

        //     for ((index, link) in links.withIndex()) {
        //         SinglePage(link, "GBK", messageText).saveTo(outdir, style = "pixyll")
        //         updateProgress((index + 1).toLong(), links.size.toLong())
        //     }
        //     messageText.appendText("下载完成\n")

        // }
    }


    class Console(private val console: TextArea) : OutputStream() {

        private fun appendText(valueOf: String) {
            Platform.runLater { console.appendText(valueOf) }
        }

        @Throws(IOException::class)
        override fun write(b: Int) {
            appendText(b.toChar().toString())
        }
    }
}

class About: Fragment() {
    override val root = VBox()

    init {
        with(root) {
            this += label("关于")
            this += label("2018.4.4深夜")
            this += label("草榴下载图片和文章的小程序")
        }
    }
}

class Help: Fragment() {
    override val root = VBox()

    init {
        with(root) {
            this += label("说明")
            this += label("双击列表中的值可以修改输入的链接，右键能够删除")
            this += label("")
            this += label("取消下载功能，由于设计原因必须下载完正在进行的链接后才能停止")
            this += label("")
            this += label("Socks代理可能由于代理本身的原因稳定性差")
        }
    }
}


fun main(args: Array<String>) {
    try{
        Application.launch(MyApp::class.java, *args)
    } catch (e:Exception) {
        println(e.message)
    }

}